package com.rndemo.rn.view;

import android.support.v4.view.ScrollingView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AbsListView;

import com.aspsine.swipetoloadlayout.OnLoadMoreListener;
import com.aspsine.swipetoloadlayout.OnRefreshListener;
import com.aspsine.swipetoloadlayout.SwipeToLoadLayout;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.rndemo.R;
import com.rndemo.rn.event.LoadMoreEvent;
import com.rndemo.rn.event.RefreshEvent;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by tzj on 2018/5/9.
 */
@ReactModule(name = RnRefreshLayoutManager.REACT_CLASS)
public class RnRefreshLayoutManager extends ViewGroupManager<SwipeToLoadLayout> implements OnRefreshListener,OnLoadMoreListener {
    protected static final String REACT_CLASS = "RCTRefreshLayout";

    private EventDispatcher mEventDispatcher;
    private SwipeToLoadLayout mLoadLayout;
    private View mChild;
    private View mTouchView;

    @Override
    public String getName() {
        return REACT_CLASS;
    }
    //todo 这里寻找touchview 最好通过js 告知，而不是计算出来的
    private ViewGroup.OnHierarchyChangeListener listener = new ViewGroup.OnHierarchyChangeListener() {
        @Override
        public void onChildViewAdded(View parent, View child) {
            if(parent == mLoadLayout){
                if(mChild != null){
                    throw new RuntimeException("必须是一个子view");
                }else{
                    mChild = child;
                    mLoadLayout.setTagetAndTouchView(mChild,mChild);
                }
            }
            if(mTouchView==null){//寻找touchView
                View view = searchTouchView(child);
                if(view != null){
                    mTouchView = view;
                    mLoadLayout.setTagetAndTouchView(mChild,mTouchView);
                }else if(child instanceof ViewGroup){
                    ViewGroup vg = (ViewGroup) child;
                    vg.setOnHierarchyChangeListener(listener);
                }
            }
        }
        @Override
        public void onChildViewRemoved(View parent, View child) {
            if(child == mChild){
                mChild = null;
                mTouchView = null;
                mLoadLayout.setTagetAndTouchView(null,null);
            }else if(child == mTouchView){
                mTouchView = null;
                mLoadLayout.setTagetAndTouchView(mChild,mChild);
            }
        }
    };

    @Override
    protected SwipeToLoadLayout createViewInstance(ThemedReactContext reactContext) {
        mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
        mLoadLayout = (SwipeToLoadLayout) LayoutInflater.from(reactContext).inflate(R.layout.rn_refresh_layout, null);
        mLoadLayout.setOnHierarchyChangeListener(listener);
        return mLoadLayout;
    }
    @Override
    public boolean needsCustomLayoutForChildren() {
        return true;
    }
    @ReactProp(name = "refreshEnable")
    public void setRefreshEnabled(SwipeToLoadLayout parent,  boolean b) {
        parent.setRefreshEnabled(b);
    }
    @ReactProp(name = "loadEnable")
    public void setLoadMoreEnabled(SwipeToLoadLayout parent,  boolean b) {
        parent.setLoadMoreEnabled(b);
    }
    @ReactProp(name = "refreshing")
    public void setRefreshing(SwipeToLoadLayout parent,  boolean b) {
        parent.setRefreshing(b);
    }
    @ReactProp(name = "loading")
    public void setLoadMoreing(SwipeToLoadLayout parent,  boolean b) {
        parent.setLoadingMore(b);
    }
    private View searchTouchView(View view){
        List<View> parents = new ArrayList<View>();
        parents.add(view);
        while (parents.size()!=0){
            List<View> childs = new ArrayList<View>();
            for (View v : parents) {
                if(isScrollAble(v)){
                    return v;
                }else{
                    if(v instanceof ViewGroup){//加入下一级的集合
                        ViewGroup vg = (ViewGroup) v;
                        for (int i = 0; i < vg.getChildCount(); i++) {
                            childs.add(vg.getChildAt(i));
                        }
                    }
                }
            }
            parents.clear();
            parents.addAll(childs);
        }
        return null;
    }
    private boolean isScrollAble(View view) {
        if (view instanceof AbsListView||
                view instanceof WebView||
                view instanceof ScrollingView) {
            return true;
        }
        return false;
    }

    public void onRefresh() {
        mEventDispatcher.dispatchEvent(new RefreshEvent(mLoadLayout.getId()));//todo 目标view
    }

    @Override
    public void onLoadMore() {
        mEventDispatcher.dispatchEvent(new LoadMoreEvent(mLoadLayout.getId()));//todo 目标view
    }

    //================== java 调 js
    @Override
    protected void addEventEmitters(ThemedReactContext reactContext, SwipeToLoadLayout view) {
        super.addEventEmitters(reactContext, view);
        view.setOnRefreshListener(this);
        view.setOnLoadMoreListener(this);
    }
    @Override
    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.<String, Object>builder()
                .put(RefreshEvent.NAME, MapBuilder.of("registrationName", "onRefresh"))
                .put(LoadMoreEvent.NAME, MapBuilder.of("registrationName", "onLoad"))
                .build();
    }

    //========================================注册命令即方法（一般js 发送给Java）
//    private static final int CMD_LOADLAYOUT_REFRESHING = 1;
//    private static final int CMD_LOADLAYOUT_LOADING = 2;
//    @Nullable
//    @Override
//    public Map<String, Integer> getCommandsMap() {
//        return MapBuilder.of(
//                "loading", CMD_LOADLAYOUT_LOADING,
//                "refreshing", CMD_LOADLAYOUT_REFRESHING
//        );
//    }
//    @Override
//    public void receiveCommand(SwipeToLoadLayout root, int commandId, @Nullable ReadableArray args) {
//        UtilRNLog.print(args.toString());
//        boolean b = false;
//        if(args.size()>0){
//            b = args.getBoolean(0);
//        }
//        switch (commandId) {
//            case CMD_LOADLAYOUT_LOADING:
//                root.setLoadingMore(b);
//                break;
//            case CMD_LOADLAYOUT_REFRESHING:
//                root.setRefreshing(b);
//                break;
//        }
//    }
}
